package handlers;

import item.Item;
import item.Trap;
import map.Direction;
import map.GameMap;
import map.GameWorld;
import map.Position;
import model.Observer;
import model.Subject;
import pausing.Pauseable;
import pausing.Pauser;
import stat.StatType;
import entity.Entity;

public abstract class MvtHandler extends Pauseable implements Observer {
	protected GameWorld world = null;
	protected Entity toMove = null;
	
	public MvtHandler(Entity toMove) {
		this.world = GameWorld.getInstance();
		this.toMove = toMove;
		toMove.getDeathSubject().register(this);
		
		MovementHandlerLibrary.getInstance().register( this.toMove, this );
		
		Pauser.addPauseable(this);
	}
	
	protected Entity getEntity() {
	    return toMove;
	}
	
	public boolean move(Direction dir) {
		GameMap map = world.getCurrentMap();
		
		if (this.isPaused()) return (false);
		
		Position oldPos = new Position(toMove.getPosition());
		Position newPos = new Position(oldPos);
		newPos.update(dir);
		
		if(world.isValidPosition(newPos)) {
			if(map.getTerrain(newPos) != null && map.getTerrain(newPos).getWalkingCost() <= toMove.getStats().getStat(StatType.MVT) && !world.isOccupied(newPos)) {
				if(map.hasItem(newPos) || map.hasTrap(newPos)) {
					if(map.hasTrap(newPos)) {
						doMove(dir, oldPos, newPos);
						Trap trap = map.getTrap(newPos);
						trap.accept(toMove.createIntVis(map));
					}
					else {
						Item item = world.getCurrentMap().getItem(newPos);
						if(item.canBeWalkedOn()) {
							doMove(dir, oldPos, newPos);
						}
						item.accept(toMove.createIntVis(map));
					}					
				}
				else if( world.getCurrentMap().hasCombatEffect( newPos ) ) {
					doMove( dir, oldPos, newPos );
					world.getCurrentMap().getCombatEffect( newPos ).accept( toMove.getEffectVisitor() );
				}
				else {
					doMove(dir, oldPos, newPos);
				}
				toMove.setDirection(dir);
				return true;
			}
			else if(world.isOccupied(newPos) && !world.getCurrentMap().getMapName().contains("combat")) {
				if(!newPos.equals(world.getAvatar().getPosition())) {
					System.out.println("Interacting");
					doInteract(world.getCurrentMap().getEntity(newPos));
				}
			}
			
			toMove.setDirection(dir);
			return false;
		}
		else {
			toMove.setDirection(dir);
			return false;
		}
	}
	
	public void doMove(Direction dir, Position oldPos, Position newPos) {
		
		toMove.move(dir);
		toMove.setDirection(dir);
		world.getCurrentMap().removeEntity(oldPos);
		world.getCurrentMap().addEntity(toMove, newPos);
		world.getCurrentMap().updateEntity(toMove, newPos);
		
	}
	
	public abstract void doInteract(Entity entity);
	
	public void update(Subject s) {
		System.out.println("You died!");
		world.getCurrentMap().removeAI(toMove);
		world.getCurrentMap().updateEntity(toMove, new Position(-1,-1));
	}
}
